/* Compat */
function getQueryVariable(variable) {
	var query = window.location.search.substring(1);
	var vars = query.split("&");
	for (var i = 0; i < vars.length; i++) {
		var pair = vars[i].split("=");
		if (decodeURIComponent(pair[0]) == variable) {
			return decodeURIComponent(pair[1]);
		}
	}
	return null;
}

function base64Decode(str) {
	try {
		return decodeURIComponent(
			Array.prototype.map
				.call(atob(str), function (c) {
					return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
				})
				.join("")
		);
	} catch (ex) {
		return atob(str);
	}
}

function base64Encode(str) {
	try {
		return btoa(
			encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
				return String.fromCharCode(parseInt(p1, 16));
			})
		);
	} catch (ex) {
		return btoa(str);
	}
}

const mergeJSON = function (target, add) {
	function isObject(obj) {
		if (typeof obj == "object") {
			for (var key in obj) {
				if (obj.hasOwnProperty(key)) {
					return true;
				}
			}
		}
		return false;
	}
	for (var key in add) {
		if (add.hasOwnProperty(key)) {
			if (target[key] && isObject(target[key]) && isObject(add[key])) {
				this.mergeJSON(target[key], add[key]);
			} else {
				target[key] = add[key];
			}
		}
	}
	return target;
};
window.mergeJSON = mergeJSON;

function date2str(x, y) {
	var z = {
		M: x.getMonth() + 1,
		d: x.getDate(),
		h: x.getHours(),
		m: x.getMinutes(),
		s: x.getSeconds(),
	};
	y = y.replace(/(M+|d+|h+|m+|s+)/g, function (v) {
		return ((v.length > 1 ? "0" : "") + z[v.slice(-1)]).slice(-2);
	});

	return y.replace(/(y+)/g, function (v) {
		return x.getFullYear().toString().slice(-v.length);
	});
}
/* libCaptcha.js 0.1 */
const libCaptcha = {
	__libCaptcha__fitContent: function () {
		if (!window.CSS || !window.CSS.supports) {
			console.warn("No supported instance of CSS.supports found!");
			return "auto";
		}
		var __fitContent;
		if (CSS.supports("height", "fit-content")) {
			__fitContent = "fit-content";
		} else if (CSS.supports("height", "-moz-fit-content")) {
			__fitContent = "-moz-fit-content";
		} else if (CSS.supports("height", "-webkit-fit-content")) {
			__fitContent = "-webkit-fit-content";
		} else {
			console.warn("No supported instance of fit-content found!");
			__fitContent = "auto";
		}
		return __fitContent;
	},
	Errors: {
		NCAPTCHA_ERROR_LOOKUP_HEADER: {
			NCAPTCHA_MISSING_COOKIE: "nCaptcha encountered an issue.",
		},
		NCAPTCHA_ERROR_LOOKUP_TEXT: {
			NCAPTCHA_MISSING_COOKIE: "Your browser seems to have not set or provided the required cookie, this typically is a browser related issue.",
		},
	},
	Locales: {
		EN: {
			/* v3 */
			"ncaptcha.lang.v3_btn": "Are you a robot?",
			"ncaptcha.lang.v3_success": "You are not a robot.",
			/* v2 */
			"ncaptcha.lang.v2_failed_to_generate": "Failed to generate captcha, sorry about that.",
			"ncaptcha.lang.v2_failed": "Captcha failed, trying again.",
			/* v2: Instructions */
			"ncaptcha.lang.v2_screenwords": "Enter the letters above.",
			"ncaptcha.lang.v2_screenwords2": "Enter the OUTLINED letters above.",
			"ncaptcha.lang.v2_screenwords3": "Enter the OUTLINED letters above.",
			"ncaptcha.lang.v2_shapes": "Enter the shape above in LOWER case.",
			"ncaptcha.lang.v2_math": "Enter the answer to the math question.",
			"ncaptcha.lang.v2_objectid": "Enter the item in the above image.",
			"ncaptcha.lang.v2_truefalse": "Is this statement TRUE of FALSE?",
			"ncaptcha.lang.v2_messedup": "Enter the second half, then the first half of the word above.",
			"ncaptcha.lang.v2_multiword": "Enter the words above.",
			"ncaptcha.lang.v2_bot_detected": "Are you a robot? We'll try again in a moment.",
			"ncaptcha.lang.v2_captcha_done": "You are not a robot.",
		},
		_getNavigatorLanguage: function () {
			if (navigator.languages && navigator.languages.length) {
				return navigator.languages[0];
			} else {
				return navigator.userLanguage || navigator.language || navigator.browserLanguage || "en";
			}
		},
		getNavigatorLanguage: function () {
			const o = this._getNavigatorLanguage().toUpperCase();
			if (o === "EN-GB" || o === "EN-US") return "EN";
			if (!this.Locales[o]) {
				console.warn("[lang.js] Unsupported locale: " + o);
				return "EN";
			}
			return o;
		},
		getString: function (_locale, id, fallback) {
			const locale = _locale === null || _locale === undefined ? libCaptcha.Locales.getNavigatorLanguage() : _locale;
			var item = libCaptcha.Locales[locale][id];
			if (item === undefined || item === null) {
				console.error("nLang: Failed to find key '" + id + "'. [locale=" + locale + "]");
				return fallback;
			} else {
				return item;
			}
		},
	},
	loadCaptcha: function (/* {
		location: [DIV],
		callback: [FUNC],
		options: {
			forceLegacy: false,
			allowV4: false
		}
	} */) {
		const args = arguments;
		if (args === null || args === undefined || args.length === 0) {
			throw new Error("Invalid arguments! [e:ARGS_BLANK]");
		}
		const div = arguments[0];
		if (!(div instanceof HTMLDivElement)) {
			throw new Error("Invalid element! [e:LOCATION_NOT_DIV]");
		}
		const callback = arguments[1];
		if (!(typeof callback === "function")) {
			throw new Error("Invalid element! [e:INVALID_CALLBACK]");
		}
		var man_args = null;
		if (arguments.length >= 3) {
			const pre_args = arguments[2];
			if (!(typeof pre_args === "object")) {
				throw new Error("Invalid element! [e:INVALID_OPTIONS]");
			}
			man_args = pre_args;
		}
		var options = {
			forceLegacy: false,
		};
		if (man_args != null) {
			options = mergeJSON(options, man_args);
		}
		div.setAttribute("ncaptcha", "present");
		function __make_v4_gyro() {}
		function __make_v2() {
			const fitContent = libCaptcha.__libCaptcha__fitContent();
			const V2_BTN_TEXT_SUCCESS = libCaptcha.Locales.getString(null, "ncaptcha.lang.v3_success", "You aren't a robot.");
			const V2_BTN_TEXT_FAILED = libCaptcha.Locales.getString(null, "ncaptcha.lang.v2_failed", "Captcha failed, trying again.");
			const V2_BTN_TEXT_ERROR = libCaptcha.Locales.getString(null, "ncaptcha.lang.v3_error", "That didn't go well, you should try again.");
			const V2_BTN_TEXT_CAP_GEN = libCaptcha.Locales.getString(null, "ncaptcha.lang.v2_failed_to_generate", "Failed to generate captcha, sorry about that.");
			const __v2_div = libWeb.DOM.create_dom("div")
				.style({
					border: "1px solid lightgreen",
					padding: "5px",
					width: fitContent,
					height: fitContent,
					textAlign: "center",
					color: "white",
					backgroundColor: "rgba(20, 20, 20, 0.9)",
				})
				.make();
			const __v2_img = libWeb.DOM.create_dom("img")
				.style({
					imageRendering: "pixelated",
					width: "100%",
				})
				.make();
			const __v2_prompt = libWeb.DOM.create_dom("p").style({ fontFamily: "sans-serif", textAlign: "center" }).text("Loading captcha...").make();
			const __v2_input = libWeb.DOM.create_dom("input")
				.style({
					width: "65%",
					display: "inline-block",
					color: "inherit",
					backgroundColor: "inherit",
					border: "1px solid lightgray",
					fontFamily: "inherit",
					padding: "5px",
				})
				.make();
			const __v2_btn = libWeb.DOM.create_dom("input")
				.style({
					color: "inherit",
					backgroundColor: "inherit",
					border: "1px solid lightgray",
					fontFamily: "inherit",
					padding: "5px",
				})
				.make();
			__v2_img.loading = "lazy";
			__v2_img.decoding = "async";
			__v2_div.appendChild(__v2_img);
			__v2_div.appendChild(__v2_prompt);
			__v2_div.appendChild(__v2_input);
			__v2_div.appendChild(__v2_btn);
			__v2_btn.type = "submit";
			__v2_btn.value = "Submit";
			function __v2_loadChallenge() {
				request(
					"/captcha/generate_captcha",
					null,
					function (exception) {
						console.error(exception);
						callback({ success: false, pending: true, method: "v2", reason: "INTERNAL_ERROR", error: exception });
						alert(V2_BTN_TEXT_CAP_GEN);
					},
					function (data) {
						var json = JSON.parse(data);
						__v2_img.src = json["image"];
						var t = json["type"];
						const type = t.split(":")[1];
						const __v2_prompt_line = libCaptcha.Locales.getString(null, "ncaptcha.lang.v2_" + type, "Unknown type... (" + type + ")");
						__v2_prompt.innerHTML = __v2_prompt_line;
						if (type === "bot_detected") {
							window.setTimeout(function () {
								__v2_btn.disabled = false;
								__v2_input.disabled = false;
								__v2_loadChallenge();
							}, 1000 * 120);
						} else if (type === "captcha_done") {
							callback({ success: true, pending: false, method: "v2" });
						}
					}
				);
			}
			__v2_btn.onclick = function () {
				__v2_btn.disabled = true;
				__v2_input.disabled = true;
				__v2_prompt.innerHTML = "Checking...";
				const m = __v2_input.value;
				var s = {};
				s["value"] = m;
				s["backend"] = "libCaptcha";
				request(
					"/captcha/check_captcha",
					JSON.stringify(s),
					function (e) {
						console.error(e);
						callback({ success: false, pending: true, method: "v2", reason: "INTERNAL_ERROR", error: e });
						alert(V2_BTN_TEXT_ERROR);
					},
					function (r) {
						var rj = JSON.parse(r);
						if (rj["result"] === "passed") {
							__v2_prompt.innerHTML = V2_BTN_TEXT_SUCCESS;
							callback({ success: true, pending: false, method: "v2" });
						} else {
							callback({ success: false, pending: true, method: "v2", reason: "CAPTCHA_FAILED" });
							__v2_prompt.innerHTML = V2_BTN_TEXT_FAILED;
							__v2_btn.disabled = false;
							__v2_input.disabled = false;
							__v2_input.value = "";
							window.setTimeout(function () {
								__v2_loadChallenge();
							}, 1500);
						}
					}
				);
			};
			div.appendChild(__v2_div);
			__v2_loadChallenge();
		}
		function __make_v3() {
			const fitContent = libCaptcha.__libCaptcha__fitContent();
			const V3_BTN_TEXT_CORE = libCaptcha.Locales.getString(null, "ncaptcha.lang.v3_btn", "Are you a robot?");
			const V3_BTN_TEXT_SUCCESS = libCaptcha.Locales.getString(null, "ncaptcha.lang.v3_success", "You aren't a robot.");
			const V3_BTN_TEXT_FALLBACK = libCaptcha.Locales.getString(null, "ncaptcha.lang.v3_fallback", "We're not sure still, trying another challenge.");
			const V3_BTN_TEXT_ERROR = libCaptcha.Locales.getString(null, "ncaptcha.lang.v3_error", "That didn't go well, you should try again.");
			const __v3_div = libWeb.DOM.create_dom("div")
				.style({
					border: "1px solid green",
					padding: "5px",
					width: fitContent,
					height: fitContent,
					textAlign: "center",
					color: "white",
					backgroundColor: "rgba(20, 20, 20, 0.9)",
				})
				.make();
			const v3_btn = libWeb.DOM.create_dom("button")
				.style({
					backgroundColor: "inherit",
					color: "inherit",
					border: "1px solid lightgray",
					fontFamily: "inherit",
					padding: "5px",
				})
				.text(V3_BTN_TEXT_CORE)
				.make();
			v3_btn.onclick = function (event) {
				v3_btn.disabled = true;
				v3_btn.innerHTML = "Proving that you are not a robot...";
				const context = {};
				context["gyro"] = options["allowV4"] && typeof Gyroscope === "function" && "WebSocket" in window && window.WebSocket.CLOSING === 2;
				request(
					"/captcha/request_auto",
					JSON.stringify(context),
					function (e) {
						console.error(e);
						callback({ success: false, pending: true, method: "v3", reason: "INTERNAL_ERROR", error: e });
						alert(V3_BTN_TEXT_ERROR);
						v3_btn.disabled = false;
						v3_btn.innerHTML = V3_BTN_TEXT_CORE;
					},
					function (data) {
						const obj = JSON.parse(data);
						const scr = document.createElement("script");
						var decrypted_mathChallenge = null;
						switch (obj.cipher) {
							case "blowfish":
								scr.innerHTML = blowfish.decrypt(obj.payload, obj.key, { cipherMode: 0, outputType: 0 });
								decrypted_mathChallenge = blowfish.decrypt(obj.math_payload, obj.key, { cipherMode: 0, outputType: 0 });
								break;
							case "xtea":
								scr.innerHTML = XXTEA.decryptFromBase64(obj.payload, obj.key);
								decrypted_mathChallenge = XXTEA.decryptFromBase64(obj.math_payload, obj.key);
								break;
							default:
								throw new Error("E:CIPHER_UNKNOWN");
						}
						document.head.appendChild(scr);
						const result = window.nCaptchaAuto.payload(obj.key, obj.cipher, {
							mathChallenge: decrypted_mathChallenge,
							safetyHash: obj["safety_hash"],
							event: event,
						});
						window.nCaptchaAuto = {};
						delete window.nCaptchaAuto;
						delete window.XXTEA;
						document.head.removeChild(scr);
						/* */
						/* */
						request(
							"/captcha/auto_submit",
							result["value"],
							function (e1) {
								console.error(e1);
								callback({ success: false, pending: true, method: "v3", reason: "INTERNAL_ERROR", error: e1 });
								alert(V3_BTN_TEXT_ERROR);
								v3_btn.disabled = false;
								v3_btn.innerHTML = V3_BTN_TEXT_CORE;
							},
							function (resp) {
								var n = JSON.parse(resp);
								if (n["passed"] === true) {
									v3_btn.innerHTML = V3_BTN_TEXT_SUCCESS;
									callback({ success: true, pending: false, method: "v3" });
								} else {
									v3_btn.innerHTML = V3_BTN_TEXT_FALLBACK;
									callback({ success: false, pending: true, method: "v3", reason: "CAPTCHA_FAILED" });
									__make_v2();
									__v3_div.style.display = "none";
									__v3_div.style.visibility = "hidden";
								}
							},
							{
								"X-NCAPTCHA-HASH": result["hash"],
							}
						);
					}
				);
			};
			__v3_div.appendChild(v3_btn);
			__v3_div.appendChild(
				libWeb.DOM.create_dom("p")
					.style({
						marginTop: "5px",
						marginBottom: "5px",
					})
					.text("Press the button above.")
					.make()
			);
			__v3_div.appendChild(
				libWeb.DOM.create_dom("p")
					.style({
						marginTop: "5px",
						marginBottom: "5px",
						fontSize: "small",
					})
					.text("nCaptcha 3.3")
					.make()
			);
			div.appendChild(__v3_div);
		}
		if (!options["forceLegacy"]) {
			__make_v3();
		} else {
			__make_v2();
		}
	},
};
window.libCaptcha = libCaptcha;
